import type { MessageData } from '../../../../shares/sharesApp';
import { ClientEvents } from '../../../../shares/sharesApp';
import { Singleton } from '../../framework/common/Singleton';
import { RoleType } from '../const/RoleType';
import { PlayerType } from '../const/TokenConst';
import { NpcMgr } from './NpcMgr';
import { PlayerMgr } from './PlayerMgr';
import { RemoteMgr } from './RemoteMgr';

export class GameMgr extends Singleton<GameMgr>() {
    /** 游玩玩家ID列表 / Playing player ID list */
    private players: string[] = [];
    /** 玩家角色类型映射 / Role type mapping */
    private _roleTypeMap: Map<string, RoleType> = new Map();
    /** 清除定时器编号 */
    private _clearTimeout: number = -1;

    /**
     * 构造函数 / Constructor
     */
    constructor() {
        super();
        console.log('(Server) GameMgr constructor');
        world.useOBB = true;
    }

    /**
     * 启动游戏 / Start game
     */
    public start(): void {
        console.log('(Server) GameMgr start');
        this.bindEvents();
    }

    private bindEvents(): void {
        world.onPlayerLeave((event) => {
            if (this.players.includes(event.entity.player.userId)) {
                this.onPlayerLeave(event.entity);
            }
        });
    }

    /**
     * 玩家加入游戏 / Player join game
     * @param userId 玩家ID / Player ID
     */
    public onPlayerJoin(userId: string) {
        if (!this.players.includes(userId)) {
            this.players.push(userId);
            if (this.players.length < 2) {
                RemoteMgr.instance.sendAll<MessageData>({
                    type: ClientEvents.MESSAGE,
                    data: {
                        contentKey: 'game.waiting',
                    },
                });
            } else if (this.players.length === 2) {
                this.players.forEach((playerId, index) => {
                    PlayerMgr.instance.changePlayerType(
                        playerId,
                        PlayerType.GamePlayer
                    );
                    const player = PlayerMgr.instance.getPlayer(playerId);
                    player?.entity?.position.copy(
                        new GameVector3(184, 33, 134)
                    );
                    if (index === 0) {
                        this.setRoleType(playerId, RoleType.Pumpkin);
                    } else {
                        this.setRoleType(playerId, RoleType.Ghost);
                    }
                });
                this._clearTimeout = setTimeout(() => {
                    this.clear();
                }, 60000);
            } else {
                const player = PlayerMgr.instance.getPlayer(userId);
                player?.entity?.position.copy(new GameVector3(184, 33, 134));
                this.setRoleType(userId, RoleType.Ghost);
            }
        }
    }

    public onPlayerLeave(entity: GamePlayerEntity) {
        if (this.players.length === 2) {
            this.clear();
        }
        const { userId } = entity.player;
        this.players = this.players.filter((playerId) => playerId !== userId);
        this._roleTypeMap.delete(userId);
        if (this.getRoleType(userId) === RoleType.Pumpkin) {
            this.createPumpkin(entity.position as GameVector3);
        }
    }

    public setRoleType(userId: string, roleType: RoleType) {
        this._roleTypeMap.set(userId, roleType);
        const player = PlayerMgr.instance.getPlayer(userId);
        if (player) {
            player.roleType = roleType;
        }
    }

    public getRoleType(userId: string): RoleType {
        return this._roleTypeMap.get(userId) as RoleType;
    }

    /**
     * 生成一个南瓜 / Generate a pumpkin
     * @param position 位置 / Position
     */
    public async createPumpkin(position: GameVector3): Promise<void> {
        world.createEntity({
            id: 'pumpkin',
            mesh: 'mesh/南瓜.vb',
            meshScale: new GameVector3(0.16, 0.16, 0.16),
            position,
        });
        NpcMgr.instance.addNpcById('pumpkin');
    }

    private clear() {
        clearTimeout(this._clearTimeout);
        const winner: string =
            PlayerMgr.instance.getPlayer(
                this.getPlayerIdByRoleType(RoleType.Pumpkin)[0]
            )?.entity?.player.name || '无人';
        RemoteMgr.instance.sendAll<MessageData>({
            type: ClientEvents.MESSAGE,
            data: {
                contentKey: 'game.result',
                params: {
                    winner,
                },
            },
        });
        this.players.forEach((playerId) => {
            PlayerMgr.instance.changePlayerType(playerId, PlayerType.OBPlayer);
            const player = PlayerMgr.instance.getPlayer(playerId);
            if (player) {
                player.entity?.position.copy(new GameVector3(8, 3, 6));
            }
        });
        this.players = [];
        this._roleTypeMap.clear();
        world.querySelectorAll('#pumpkin').forEach((entity) => {
            entity.destroy();
        });
    }

    /**
     * 获取指定角色类型的玩家ID
     * @param roleType 角色类型
     * @returns 玩家ID
     */
    public getPlayerIdByRoleType(roleType: RoleType): string[] {
        const playerIds: string[] = [];

        this._roleTypeMap.forEach((type, playerId) => {
            if (type === roleType) {
                playerIds.push(playerId);
            }
        });

        return playerIds;
    }
}
